package com.codechuan.didi_web.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.codechuan.didi_web.common.Constant;
import com.codechuan.didi_web.entity.*;
import com.codechuan.didi_web.mapper.SysUserAccountMapper;
import com.codechuan.didi_web.mapper.SysUserOrderMapper;
import com.codechuan.didi_web.mapper.SysUserTokenMapper;
import com.codechuan.didi_web.service.ThreadManagerService;
import com.codechuan.didi_web.thread.GetAnOrderThread;
import com.codechuan.didi_web.thread.ScheduleThread;
import com.codechuan.didi_web.utils.DiDiHttpUtil;
import com.codechuan.didi_web.utils.ResultUtils;
import com.codechuan.didi_web.vo.ResultVO;
import okhttp3.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class ThreadManagerServiceImpl implements ThreadManagerService {
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private SysUserTokenMapper sysUserTokenMapper;

    @Resource
    private SysUserOrderMapper sysUserOrderMapper;

    @Resource
    private SysUserAccountMapper sysUserAccountMapper;


    /**
     * @param account 用户账户/卡密
     * @param ticket  用户的token
     * @return 返回启动成功或停止成功
     * @Deprecated 执行抢单
     */
    @Override
    public String startOrEndThread(String account, String ticket, HashMap<String, Object> map, SysUserConfig sysUserConfig, List<String> minTokenList) {
        // 获取用户是否启动
        String value = redisTemplate.opsForValue().get(account);
        // 如果行程刷单获取发布的行程列表
        ArrayList<SysSchedule> mySubmitSchedule = null;
        if (sysUserConfig.getQueryType().equals("1")) {
            mySubmitSchedule = getMySubmitSchedule(ticket);
        }

        // 校验是否行程刷单
        if (sysUserConfig.getQueryType().equals("1")) {
            if (mySubmitSchedule == null || mySubmitSchedule.isEmpty()) {
                return "请先去滴滴发布一个行程哦~";
            }
        }
        // 判断是否存在主号{没有主号不能刷单}
        if (minTokenList.isEmpty() && sysUserConfig.getGbzhsxCheck().equals("true")) {
            return "您无小号请勿开启主号不参与刷新!";
        }

        // 判断redis中是否存在这个用户,不存在则直接启动线程,并设置状态为一(启动)
        if (ObjectUtils.isEmpty(value)) {
            // 存入redis
            redisTemplate.opsForValue().set(account, "isStart:1");
            // 大厅刷单
            if (sysUserConfig.getQueryType().equals("0")) {
                // 校验主号是否过期
                if (checkCloseMainNumberFlush(account, ticket, map, sysUserConfig))
                    return "主号已经失效";
                // 获取小号列表,并且校验每个小号是否登录过期
                for (String miniToken : minTokenList) {
                    SysCarInfo sysCarInfo = checkAccount(miniToken);
                    if (sysCarInfo == null) {
                        return miniToken + "小号登录已经失效";
                    }
                    // 获取小号刷新延时
                    Integer sxTime = sysUserTokenMapper.selectSxTime(miniToken);
                    Constant.executorService.execute(new GetAnOrderThread(account, redisTemplate, ticket, miniToken, map, sysUserOrderMapper, sysUserConfig, sysUserTokenMapper, sxTime, sysCarInfo));
                }
            } else {
                // 行程刷单
                SysCarInfo sysCarInfo = checkAccount(ticket);
                if (sysCarInfo == null) {
                    return "主号登录已经失效";
                }
                Constant.executorService.execute(new ScheduleThread(account, redisTemplate, ticket, map, sysUserOrderMapper, sysUserConfig, sysUserTokenMapper, mySubmitSchedule, sysCarInfo));
            }
        } else {
            // 取出该账户的信息,切割后取右边的isStart 0为停止中 1为抢单中
            String[] split = value.split(":");
            // 如果为一则取反设置为0返回关闭成功
            if (split[1].equals("1")) {
                redisTemplate.opsForValue().set(account, "isStart:0");
                return "关闭成功";
            } else {
                // 如果为一则取反设置为1返回启动成功
                redisTemplate.opsForValue().set(account, "isStart:1");
                // 大厅刷单
                if (sysUserConfig.getQueryType().equals("0")) {
                    // 校验主号是否过期
                    if (checkCloseMainNumberFlush(account, ticket, map, sysUserConfig))
                        return "主号已经失效";
                    // 获取小号列表,并且校验每个小号是否登录过期
                    for (String miniToken : minTokenList) {
                        SysCarInfo sysCarInfo = checkAccount(miniToken);
                        if (sysCarInfo == null) {
                            return miniToken + "小号登录已经失效";
                        }
                        // 获取小号刷新延时
                        Integer sxTime = sysUserTokenMapper.selectSxTime(miniToken);
                        Constant.executorService.execute(new GetAnOrderThread(account, redisTemplate, ticket, miniToken, map, sysUserOrderMapper, sysUserConfig, sysUserTokenMapper, sxTime, sysCarInfo));
                    }
                } else {
                    // 行程刷单
                    SysCarInfo sysCarInfo = checkAccount(ticket);
                    if (sysCarInfo == null) {
                        return "主号登录已经失效";
                    }
                    Constant.executorService.execute(new ScheduleThread(account, redisTemplate, ticket, map, sysUserOrderMapper, sysUserConfig, sysUserTokenMapper, mySubmitSchedule, sysCarInfo));
                }
                return "启动成功";
            }
        }
        return "启动成功";
    }

    /**
     * @return
     * @Deprecated 校验是否开启主号刷新
     */
    private boolean checkCloseMainNumberFlush(String account, String ticket, HashMap<String, Object> map, SysUserConfig sysUserConfig) {
        if (!sysUserConfig.getGbzhsxCheck().equals("true")) {
            // 校验主号是否失效
            SysCarInfo sysCarInfo = checkAccount(ticket);
            if (sysCarInfo == null) {
                return true;
            }
            Constant.executorService.execute(new GetAnOrderThread(account, redisTemplate, ticket, ticket, map, sysUserOrderMapper, sysUserConfig, sysUserTokenMapper, sysUserConfig.getSxNumber(), sysCarInfo));
        }
        return false;
    }

    /**
     * @param mainTicket
     * @return
     * @Deprecated 校验主号是否登录过期, 并且获取车辆信息
     */
    private SysCarInfo checkAccount(String mainTicket) {
        // js算法结果
        String secdd_challenge = "1,com.sdu.didi.psnger|1.0.28||||0||";
        // 认证信息
        String secdd_authentication = "c9b8d7050edfdbda045b14aa7b5d4db484ec7abb1fc410d6b830385e4199d4e721eb3ed4272eb36b32a9d8887eee556a27437a569101000001000000";
        // 获取车辆信息
        DiDiHttpUtil diDiHttpUtil = new DiDiHttpUtil();
        return diDiHttpUtil.getDriverVehicleInformation(mainTicket, secdd_authentication, secdd_challenge);
    }

    /**
     * @param account 用户账户/卡密
     * @param ticket  用户token
     * @return 返回查询到的行程列表
     * @Deprecated 获取自己发布的行程列表
     */
    @Override
    public ResultVO<Object> getMySubmitSchedule(String account, String ticket) {
        DiDiHttpUtil diDiHttpUtil = new DiDiHttpUtil();
        return ResultUtils.success(diDiHttpUtil.getMySubmitSchedule(ticket));
    }

    /**
     * @param ticket 主号ticket
     * @return 返回行程列表集合
     * @Deprecated 刷单接口专用获取行程
     */
    public ArrayList<SysSchedule> getMySubmitSchedule(String ticket) {
        DiDiHttpUtil diDiHttpUtil = new DiDiHttpUtil();
        return diDiHttpUtil.getMySubmitSchedule(ticket);
    }

    /**
     * @param phone 手机号
     * @return 返回发送结果
     * @Deprecated 发送短信验证码
     */
    @Override
    public ResultVO<Object> sendSms(String phone) {
        DiDiHttpUtil diDiHttpUtil = new DiDiHttpUtil();
        diDiHttpUtil.sendCodeWeChatMiniInit();
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("api_version", "1.0.1");
        hashMap.put("appid", 35009);
        hashMap.put("role", 1);
        hashMap.put("extra_info", "{\"channel\":1100000004}");
        hashMap.put("device_name", "Pixel 3");
        String name = "Ny3d38n" + getRandomAlphanumeric(6) + "UVdBHzEB2HLTUdH8Sl661KCqZvgeewleJZUedUiuxPw98IptM";
        hashMap.put("sec_session_id", name);
        hashMap.put("policy_name_list", new ArrayList<>());
        hashMap.put("ddfp", UUID.randomUUID().toString().replaceAll("", ""));
        hashMap.put("lang", "zh-CN");
        hashMap.put("wsgenv", "");
        hashMap.put("cell", String.valueOf(phone));
        hashMap.put("country_calling_code", "+86");
        hashMap.put("code_type", 0);
        hashMap.put("scene", 1);
        String jsonString = JSONObject.toJSONString(hashMap);
        String encode = URLEncoder.encode(jsonString);
        String param = "lang=zh-CN&token=&access_key_id=9&appversion=6.8.50&channel=1100000004&_ds=&xpsid=4ed3890f8b759bd7a02bf1f05f603f4b&xpsid_root=4ed3890f8b759bd7a02bf1f05f603f4b&q="
                + encode;

        String s = "";
        try {
            s = diDiHttpUtil.sendCodeWeChatMini(param);
            JSONObject jsonObject = JSONObject.parseObject(s);
            return ResultUtils.success(jsonObject.getString("error"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public static String getRandomAlphanumeric(int count) {
        StringBuilder builder = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            boolean isUpperCase = random.nextBoolean(); // 50% chance of upper case
            char c = isUpperCase ? (char) (random.nextInt(26) + 'A') // Upper case
                    : (char) (random.nextInt(26) + 'a'); // Lower case
            builder.append(c);
        }
        return builder.toString();
    }


    /**
     * @param phone   手机号
     * @param code    验证码
     * @param account 账户/卡密
     * @return 返回发送结果
     * @Deprecated 滴滴微信小程序登录
     */
    @Override
    public ResultVO<Object> loginDiDi(String phone, CharSequence code, String account, String type) {

        DiDiHttpUtil diDiHttpUtil = new DiDiHttpUtil();
        Map<String, String> header = new HashMap<>();
        header.put("Host", "epassport.diditaxi.com.cn");
        header.put("secdd-authentication", "");
        header.put("charset", "utf-8");
        header.put("mpxlogin-ver", "5.4.30");
        header.put("didi-header-rid", getMD5(String.valueOf(Instant.now().toEpochMilli())));
        header.put("User-Agent", "Mozilla/5.0 (Linux; Android 12; Pixel 3 Build/SP1A.210812.016.C2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.120 Mobile Safari/537.36 XWEB/1220067 MMWEBSDK/20240404 MMWEBID/3880 MicroMessenger/8.0.49.2600(0x28003156) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android");
        header.put("content-type", "application/x-www-form-urlencoded");
        header.put("secdd-challenge", " 3|v1.1.0||||||");
        header.put("didi-header-hint-content", " {\"lang\":\"zh-CN\",\"Cityid\":173}");
        header.put("Referer", " https://servicewechat.com/wxaf35009675aa0b2a/866/page-frame.html");
        String uuidString = UUID.randomUUID().toString().replaceAll("-", "");
        String param = "lang=zh-CN&token=&access_key_id=9&appversion=6.8.50&channel=1100000004&_ds=&xpsid=" + uuidString +
                "&xpsid_root=" + uuidString +
                "&q=%7B%22api_version%22:%221.0.1%22,%22appid%22:35009,%22role%22:1,%22extra_info%22:%7B%22channel%22:1100000004%7D,%22device_name%22:%22Pixel%203%22,%22sec_session_id%22:%22tpZmRquXk" + "生成6位字符" +
                "vZtNd5ZHuSPwrfNnGz8PwSZVsX7XxrTqIOy07VSpvFYnlzabL%22,%22policy_id_list%22:[50001289],%22policy_name_list%22:[],%22ddfp%22:%22" +
                uuidString + "%22,%22lang%22:%22zh-CN%22,%22wsgenv%22:%22%22,%22cell%22:%22" + phone + "%22,%22country_calling_code%22:%22%2B86%22,%22code%22:%22"
                + code + "%22,%22oauthcode%22:%220c3XXD000ckUeS12Ry2005lhTb1XXD0l%22%7D";
        String s = null;
        try {
            s = diDiHttpUtil.weChatMiniLogin("https://epassport.diditaxi.com.cn/passport/login/v5/signInByCode?wsgsig=dd03-HXijLaL4nkBdbIaGeUGg9VPNVdrbgSqCg%2FzGEUdIVdrcbOdJFdfc9e61kUBcb26Aa9v8cFI7llL9ELa5ekiealIBkk29GId9eUvGa%2FM1lkk09IM1AauJaqe8khA", param, header);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        JSONObject jsonObject = JSONObject.parseObject(s);
        if (jsonObject.getString("errno").equals("0")) {
            // 滴滴的token
            String ticket = jsonObject.getString("ticket");
            // 获取卡密信息
            String accountData = redisTemplate.opsForValue().get(account);
            String keyNumber = JSONObject.parseObject(accountData).getString("keyNumber");
            // 判断该用户是否有主号
            String s1 = sysUserTokenMapper.selectMainTokenByAccount(keyNumber);
            if (s1 != null && type.equals("0")) {
                return ResultUtils.success("您已存在主号无法继续添加.");
            }
            // todo 存入数据库
            SysUserToken sysUserToken = new SysUserToken();
            sysUserToken.setKeyNumber(keyNumber);
            sysUserToken.setType(type);
            sysUserToken.setToken(ticket);
            sysUserToken.setTokenStatus("正常");
            sysUserToken.setSxNumber(type.equals("0") ? null : 1000);
            sysUserTokenMapper.insert(sysUserToken);
            return ResultUtils.success("提码成功");
        }
        return ResultUtils.success(jsonObject.getString("error"));
    }

    /**
     * @param address 地址
     * @return 返回经纬度和cityId
     * @Deprecated 虚拟定位
     */
    @Override
    public ResultVO<Object> virtualPositioning(String address) {
        if (address == null || address.isEmpty())
            return ResultUtils.error(500, "位置不能为空", "位置不能为空");

        String encode = URLEncoder.encode(address);
        String url = "https://restapi.amap.com/v3/geocode/geo?address=" + address + "&output=JSON&key=7faf050e5f054d4f76fe47fefa6fb2dc";
        ;
        String result = null;
        try {
            result = doGet1(url);
        } catch (IOException e) {
            return ResultUtils.error(500, "系统异常", "系统异常");
        }

        JSONObject parseObject = JSONObject.parseObject(result);
        JSONArray dataList = JSONObject.parseArray(parseObject.getString("geocodes"));
        if (dataList.isEmpty()) {
            return ResultUtils.error(500, "位置设置错误", "位置设置错误");
        }
        JSONObject one = JSONObject.parseObject(dataList.get(0).toString());
        String city = one.getString("city");
        String adCode = one.getString("adcode");
        String location = one.getString("location");
        String[] split = location.split(",");
        String lat = split[1];
        String lng = split[0];
        String cityId = "";
        try {
            boolean isJump = false;

            //String json = new String(Files.readAllBytes(Paths.get("C:\\Users\\Administrator\\Desktop\\city.txt")));
           String json = new String(Files.readAllBytes(Paths.get("/home/city.txt")));
            // 打印读取到的JSON内容
            JSONObject jsonObject = JSONObject.parseObject(json);
            JSONArray jsonArray = JSONObject.parseArray(jsonObject.getString("groups"));
            for (int i = 0; i < jsonArray.size(); i++) {
                if (i != 0) {
                    if (isJump)
                        break;
                    JSONObject object = JSONObject.parseObject(jsonArray.get(i).toString());
                    String cities = object.getString("cities");
                    JSONArray citiArray = JSONObject.parseArray(cities);
                    for (Object o : citiArray) {
                        JSONObject jsonObject1 = JSONObject.parseObject(o.toString());
                        if (jsonObject1.getString("name").equals(city)) {
                            cityId = jsonObject1.getString("cityid");
                            isJump = true;
                            break;
                        }
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        CityInfo cityInfo = new CityInfo();
        cityInfo.setCity(city);
        cityInfo.setLng(lng);
        cityInfo.setLat(lat);
        cityInfo.setCityId(cityId);
        // 通过城市名称获取邮编和城市区号
        cityInfo.setAdCode(adCode);
        return ResultUtils.success(cityInfo);
    }

    /**
     * @param token 滴滴token
     * @Deprecated 删除用户token
     */
    @Override
    public ResultVO<Object> deleteToken(String token) {
        sysUserTokenMapper.deleteByToken(token);
        return ResultUtils.success(null, "删除成功");
    }


    /**
     * 以get方式调用第三方接口
     *
     * @param url 请求地址
     */
    public static String doGet1(String url) throws IOException {
        OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            assert response.body() != null;
            return response.body().string();
        }
    }

    /**
     * @param text 时间戳
     * @return 返回加密结果
     * @Deprecated 时间转MD5
     */
    public static String getMD5(String text) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(text.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            System.out.println("e = " + e);
            return null;
        }
    }
}
